"""
mathmodeling_SAK.Calc3D._data_process
=====================================

定义了三维坐标运算所需要的一些数据处理过程，如标准化等。这些方法不应该
直接在外部调用，而是作为 :module:`mathmodeling_SAK.Calc3D.clac_3D`
依赖的工具被从其他模块调用。
"""

import numpy as np

def scale(data):
    """ 数据归一化
    """
    min_vals = np.min(data)
    max_vals = np.max(data)
    scale = max_vals - min_vals
    if scale == 0:
        scale = 1  # 防止除以零
    scaled_data = (data - min_vals) / scale
    return scaled_data, min_vals, scale

def unscale(scaled_data, min_vals, scale):
    """ 将归一化数据转换回原始数据
    """
    original_data = (scaled_data * scale) + min_vals
    return original_data

# 下面的两个方法专用于坐标点和距离向量

def scale_points_and_distances(points, distances):
    """
    将坐标点和距离向量标准化到范围 `[0, 1]`

    参数
    ----------
    points : numpy.array
        需要进行标准化的坐标点
    distances : numpy.array
        需要进行标准化的距离向量

    返回值
    ----------
    scaled_points : numpy.array
        经过标准化之后的坐标点
    scaled_distances : numpy.array
        经过标准化之后的距离值
    min_vals : float
        标准化方法返回的 `points` 坐标矩阵中最小的元素，
        作为标准化过程的下界。可用于反标准化解出坐标点。
    scale : float
        标准化方法返回的标准化尺度 `scale`，作为标准化
        过程的下界。可用于反标准化解出坐标点。

    """
    min_vals = np.min(points, axis=0)
    max_vals = np.max(points, axis=0)
    scale = max_vals - min_vals
    scaled_points = (points - min_vals) / scale
    scaled_distances = distances / np.linalg.norm(scale)
    return scaled_points, scaled_distances, min_vals, scale

def unscale_point_and_distance(point, min_vals, scale):
    """
    将解析出的点反标准化到标准尺度

    参数
    ----------
    point : numpy.array
        需要进行反标准化的坐标点
    min_vals : float
        标准化方法返回的 `points` 坐标矩阵中最小的元素，
        作为标准化过程的下界。可用于反标准化解出坐标点。
    scale : float
        标准化方法返回的标准化尺度 `scale`，作为标准化
        过程的下界。可用于反标准化解出坐标点。

    返回值
    ----------
    unscaled_point : numpy.array
        反标准化的坐标点

    """
    unscaled_point = point * scale + min_vals
    return unscaled_point